package com.example.demo.util.beanUtils.utils4;

import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;


/**
 * 转化工具类 自定义 ：https://github.com/w4824112w/ywgk/blob/73e8c74d61ec2e23b9702a001bedb48d23798897/src/main/java/com/gkyt/ywgk/commons/utils/ConvertUtil.java
 *
 * @author hk   星21.1
 *
 */
public class ConvertUtil_diy {

    /**
     * @ 将相关字典表查询list信息合并到主业务查询数据List中(list数据强关联,mainList中存在匹配到dictList的数据才会返回)
     *
     * @param mainList
     *            主业务数据的list
     * @param dictList
     *            相关字典表信息list
     * @param mainKey
     *            主业务数据中和字典信息关联的字段,主业务表中不含有该键值的数值,则直接返回主业务数据
     * @param dictKey
     *            字典信息中和主业务数据关联的字段,字典表中不含有该键值的数值,则直接返回主业务数据
     * @return List
     */
    public static List<Map<String, Object>> mergeList(
            List<Map<String, Object>> mainList,
            List<Map<String, Object>> dictList, String mainKey, String dictKey) {
        // 结果返回的List
        List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();

        // 防空校验
        if (mainList == null || dictList == null) {
            return returnList;
        }

        // 循环主业务数据的List
        for (Map<String, Object> mainMap : mainList) {
            String mainValue = mainMap.get(mainKey) != null ? mainMap.get(
                    mainKey).toString() : null;
            // 如果主业务表中不存在以mainKey为键值的字段则直接返回主业务数据
            if (null == mainValue) {
                return mainList;
            }
            String dictValue = "";
            // 每条主业务数据和字典表信息依次去匹配
            for (Map<String, Object> dictMap : dictList) {
                dictValue = dictMap.get(dictKey) != null ? dictMap.get(dictKey)
                        .toString() : null;
                // 如果字典表中不存在以dictKey为键值的字段则直接返回主业务数据
                if (null == dictValue) {
                    return mainList;
                }
                // 迭代字典表信息
                Iterator<Entry<String, Object>> it = dictMap.entrySet()
                        .iterator();
                // 主业务信息中比较字段的值和字典信息中比较字段的值相等则将该条字典表数据合并到当前迭代的主业务信息数据中
                if (mainValue.equals(dictValue)) {
                    while (it.hasNext()) {
                        Entry<String, Object> dictEntry = (Entry<String, Object>) it
                                .next();
                        // 将字典表信息中和主业务信息中重复的key的字段去掉,剩余的合并到主业务信息中
                        if (!mainMap.containsKey(dictEntry.getKey())) {
                            mainMap.put(dictEntry.getKey(),
                                    dictEntry.getValue());
                        }

                    }
                    returnList.add(mainMap);
                    break;
                }
            }
        }
        // 主业务数据和字典表数据无匹配的数据也直接返回主业务数据
        return returnList.isEmpty() ? mainList : returnList;
    }

    /**
     * @ 将相关字典表查询list信息合并到主业务查询数据List中(list数据左关联,mainList中存在匹配到dictList的数据有值,
     * 其余的没值)
     *
     * @param mainList
     *            主业务数据的list
     * @param dictList
     *            相关字典表信息list
     * @param mainKey
     *            主业务数据中和字典信息关联的字段,主业务表中不含有该键值的数值,则直接返回主业务数据
     * @param dictKey
     *            字典信息中和主业务数据关联的字段,字典表中不含有该键值的数值,则直接返回主业务数据
     * @return List
     */
    public static List<Map<String, Object>> mergeListLeft(
            List<Map<String, Object>> mainList,
            List<Map<String, Object>> dictList, String mainKey, String dictKey) {
        // 结果返回的List
        List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();

        // 防空校验
        if (mainList == null || dictList == null) {
            return returnList;
        }

        // 循环主业务数据的List
        for (Map<String, Object> mainMap : mainList) {
            String mainValue = mainMap.get(mainKey) != null ? mainMap.get(
                    mainKey).toString() : null;
            // 如果主业务表中不存在以mainKey为键值的字段则直接返回主业务数据
            if (null == mainValue) {
                return mainList;
            }
            String dictValue = "";
            // 每条主业务数据和字典表信息依次去匹配
            int dictListSize = dictList.size();
            int currentSize = 0;
            for (Map<String, Object> dictMap : dictList) {
                dictValue = dictMap.get(dictKey) != null ? dictMap.get(dictKey)
                        .toString() : null;
                // 如果字典表中不存在以dictKey为键值的字段则直接返回主业务数据
                if (null == dictValue) {
                    return mainList;
                }
                // 迭代字典表信息
                Iterator<Entry<String, Object>> it = dictMap.entrySet()
                        .iterator();
                // 主业务信息中比较字段的值和字典信息中比较字段的值相等则将该条字典表数据合并到当前迭代的主业务信息数据中
                // 存在匹配值的时候将字典表信息加入业务表数据
                if (mainValue.equals(dictValue)) {
                    while (it.hasNext()) {
                        Entry<String, Object> dictEntry = (Entry<String, Object>) it
                                .next();
                        // 将字典表信息中和主业务信息中重复的key的字段去掉,剩余的合并到主业务信息中
                        if (!mainMap.containsKey(dictEntry.getKey())) {
                            mainMap.put(dictEntry.getKey(),
                                    dictEntry.getValue());
                        }
                    }
                    returnList.add(mainMap);
                    break;
                    // 字典没有匹配的数据,将字典表的值清空放入业务表
                } else {
                    if (++currentSize == dictListSize) {
                        dealIterator(mainMap, it);
                        returnList.add(mainMap);
                    }
                }
            }

        }

        // 主业务数据和字典表数据无匹配的数据也直接返回主业务数据
        return returnList.isEmpty() ? mainList : returnList;
    }

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param mainMap
     * @param it
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private static void dealIterator(Map<String, Object> mainMap,
                                     Iterator<Entry<String, Object>> it) {
        while (it.hasNext()) {
            Entry<String, Object> dictEntry = (Entry<String, Object>) it.next();
            // 将字典表信息中和主业务信息中重复的key的字段去掉,剩余的合并到主业务信息中
            if (!mainMap.containsKey(dictEntry.getKey())) {
                mainMap.put(dictEntry.getKey(), null);
            }
        }
    }

    public static Map<String, Object> ConvertObjToMap(Object obj) {
        Map<String, Object> reMap = new HashMap<String, Object>();
        if (obj == null)
            return null;
        Field[] fields = obj.getClass().getDeclaredFields();
        try {
            for (int i = 0; i < fields.length; i++) {
                try {
                    Field f = obj.getClass().getDeclaredField(
                            fields[i].getName());
                    f.setAccessible(true);
                    Object o = f.get(obj);
                    reMap.put(fields[i].getName(), o);
                } catch (NoSuchFieldException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return reMap;
    }

    /**
     * 将Map对象通过反射机制转换成Bean对象
     *
     * @param map
     *            存放数据的map对象
     * @param clazz
     *            待转换的class
     * @return 转换后的Bean对象
     * @throws Exception
     *             异常
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz)
            throws Exception {
        T obj = clazz.newInstance();
        if (map != null && map.size() > 0) {
            for (Entry<String, Object> entry : map.entrySet()) {
                String propertyName = entry.getKey(); // 属性名
                Object value = entry.getValue();
                String setMethodName = "set"
                        + propertyName.substring(0, 1).toUpperCase()
                        + propertyName.substring(1);
                Field field = getClassField(clazz, propertyName);
                if (field == null)
                    continue;
                Class<?> fieldTypeClass = field.getType();
                value = convertValType(value, fieldTypeClass);
                try {
                    clazz.getMethod(setMethodName, field.getType()).invoke(obj,
                            value);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }
        return obj;
    }

    /**
     * 获取指定字段名称查找在class中的对应的Field对象(包括查找父类)
     *
     * @param clazz
     *            指定的class
     * @param fieldName
     *            字段名称
     * @return Field对象
     */
    private static Field getClassField(Class<?> clazz, String fieldName) {
        if (Object.class.getName().equals(clazz.getName())) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }

        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {// 简单的递归一下
            return getClassField(superClass, fieldName);
        }
        return null;
    }

    /**
     * 将Object类型的值，转换成bean对象属性里对应的类型值
     *
     * @param value
     *            Object对象值
     * @param fieldTypeClass
     *            属性的类型
     * @return 转换后的值
     */
    private static Object convertValType(Object value, Class<?> fieldTypeClass) {
        Object retVal = null;
        if (value == null) {
            return retVal;
        }
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Double.parseDouble(value.toString());
        } else if (String.class.getName().equals(fieldTypeClass.getName())) {
            retVal = value.toString();
        } else if (Boolean.class.getName().equals(fieldTypeClass.getName())
                || boolean.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Boolean.parseBoolean(value.toString());
        } else if (Byte.class.getName().equals(fieldTypeClass.getName())
                || byte.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Byte.parseByte(value.toString());
        } else {
            retVal = value;
        }
        return retVal;
    }

    /**
     * 将 List<Map>对象转化为List<JavaBean>
     *
     * @param listMap
     * @param T
     * @return
     * @throws Exception
     */
    public static <T> List<T> convertListMap2ListBean(
            List<Map<String, Object>> listMap, Class<T> T) throws Exception {
        List<T> beanList = new ArrayList<>();
        if (listMap != null && !listMap.isEmpty()) {
            for (int i = 0, n = listMap.size(); i < n; i++) {
                Map<String, Object> map = listMap.get(i);
                T bean = mapToBean(map, T);
                beanList.add(bean);
            }
            return beanList;
        }
        return beanList;
    }

    /**
     * 将 List<JavaBean>对象转化为List<Map>
     *
     * @param beanList
     * @return
     * @throws Exception
     */
    public static <T> List<Map<String, Object>> convertListBean2ListMap(
            List<T> beanList, Class<T> T) throws Exception {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (int i = 0, n = beanList.size(); i < n; i++) {
            Object bean = beanList.get(i);
            Map<String, Object> map = ConvertObjToMap(bean);
            mapList.add(map);
        }
        return mapList;
    }

//    public static void main(String[] args) {
//        Jails jails = new Jails();
//        jails.setId(1);
//        jails.setTitle("测试监狱");
//        jails.setZipcode("9999");
//
//        Map<String, Object> map = ConvertObjToMap(jails);
//        System.out.println(map);
//
//        /*
//         * Map map = new HashMap<String, Object>(); map.put("id", 1);
//         * map.put("title", "测试监狱"); map.put("zipcode", "9999");
//         */
//
//        List<Map<String, Object>> mainList = new ArrayList<Map<String, Object>>();
//        List<Map<String, Object>> dictList = new ArrayList<Map<String, Object>>();
//        Map<String, Object> src = new HashMap<String, Object>();
//        Map<String, Object> dest = new HashMap<String, Object>();
//
//        src.put("id", 1);
//        src.put("title", "测试监狱");
//        src.put("zipcode", "9999");
//        src.put("jailId", 70);
//        src.put("familyId", 440);
//        mainList.add(src);
//
//        dest.put("id", 440);
//        dest.put("phone", "bJx+b0xMuWeCqSysgCymSA==");
//        dest.put("phone", "upWQKhAWGYl2hq6inUvCFirlQXd3DEtX");
//        dest.put("name", "唐婉媚");
//        dest.put("jailId", 70);
//        dest.put("avatarUrl", "http://123.57.7.159/image-server/avatars/4e1d240601333746c14666f227b3b8e9_avatar-1526961656143.jpg");
//        dest.put("idCardFront", "http://123.57.7.159/image-server/uuids/4e1d240601333746c14666f227b3b8e9_front-1526961659841.jpg");
//        dest.put("idCardBack", "http://123.57.7.159/image-server/uuids/4e1d240601333746c14666f227b3b8e9_back-1526961662715.jpg");
//        dictList.add(dest);
//        List<Map<String, Object>> returnList=mergeList(mainList, dictList, "familyId", "id");
//        System.out.println("map----"+returnList.get(0).toString());
//        try {
//
//            Jails jail = (Jails) ConvertUtil.mapToBean(map, Jails.class);
//            System.out.println(jail.getTitle());
//            System.out.println(jail.getTitle());
//            System.out.println(jail.getZipcode());
//
//        } catch (Exception e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
//    }
}